package core

import (
	"bufio"
	"encoding/json"
	"errors"
	"io"
	"io/ioutil"
	"log"
	"os"
	"regexp"
	"spirit/utils"
	"strconv"
	"strings"
)

const (
	DefaultConfigFilePath = "./application.properties"
)

type Configuration struct {
	App struct {
		ServerPort   string `json:"serverPort"`
		StaticRoot   string `json:"staticRoot"`
		StaticPrefix string `json:"staticPrefix"`
		TemplateDir  string `json:"templateDir"`
		ContextPath  string `json:"contextPath"`
	} `json:"app"`
	Mongo struct {
		Addr     string `json:"addr"`
		PoolSize int    `json:"poolSize"`
		DbName   string `json:"dbName"`
	} `json:"mongo"`
	Redis struct {
		Addr        string `json:"addr"`
		Modules      string `json:"modules"`
		PoolMaxSize int    `json:"maxSize"`
		PoolMaxIdle int    `json:"maxIdle"`
		IdleTimeout int    `json:"idleTimeOut"`
	} `json:"redis"`

	Elastic struct {
		Addr     string `json:"addr"`
		PoolSize int    `json:"poolSize"`
	} `json:"elastic"`
}

var _cfg *Configuration = nil

func GetConfiguration() *Configuration {
	return _cfg
}
func SetConfiguration(c *Configuration) {
	_cfg = c
}

func initConfiguration(path string) (error, *Configuration) {
	log.Println("开始加载配置文件......")
	if utils.IsEmpty(path) {
		return errors.New("配置文件路径错误"), nil
	}
	fi, err := os.Open(path)
	if err != nil {
		log.Fatalf("加载系统配置文件出错,[%s]\n", err)
		return err, nil
	}
	defer fi.Close()
	br := bufio.NewReader(fi)
	cfg := make(map[string]map[string]interface{}, 0)
	reg := regexp.MustCompile(`(\w+).(\w+)$`)
	numReg := regexp.MustCompile(`^\d{1,5}$`)
	floatReg := regexp.MustCompile(`^(-?\d+)(\.\d+)?$`)
	for {
		lineBs, _, err := br.ReadLine()
		if err == io.EOF {
			break
		}
		str := string(lineBs)
		if len(str) == 0 || strings.HasPrefix(str, "#") {
			continue
		}
		str = strings.TrimSpace(str)
		o := strings.Split(str, "=")
		if len(o) == 2 {
			if reg.MatchString(o[0]) {
				matchArray := reg.FindStringSubmatch(o[0])
				//matchArray数组0是第一个匹配项  1,2是子串儿
				moduleName := matchArray[1]
				propertiesName := matchArray[2]
				//fmt.Println("moduleName:", moduleName, "propertiesName:", propertiesName)
				if _, ok := cfg[moduleName]; !ok {
					cfg[moduleName] = make(map[string]interface{}, 0)
				}
				var val interface{}
				if numReg.MatchString(o[1]) {
					val, _ = strconv.Atoi(o[1])
				} else if floatReg.MatchString(o[1]) {
					val, _ = strconv.ParseFloat(o[1], 64)
				} else {
					val = o[1]
				}
				cfg[moduleName][propertiesName] = val
			}
		}
	}
	bs, err := json.Marshal(cfg)
	if err != nil {
		log.Fatalln("系统配置参数转换出错:", err)
		return err, nil
	}
	config := Configuration{}
	err = json.Unmarshal(bs, &config)
	if err != nil {
		log.Fatalln("系统配置参数转换出错:", err)
		return err, nil
	}
	log.Println("系统基本配置信息:", string(bs))
	SetConfiguration(&config)
	return nil, &config
}

func ReadConfig(config interface{}) error {
	fi, err := os.Open("./config.json")
	if err != nil {
		log.Fatalln("打开系统配置文件出错", err)
		return err
	}
	defer fi.Close()
	bs, err := ioutil.ReadAll(fi)
	if err != nil {
		log.Fatalln("加载系统配置文件出错", err)
	}
	err = json.Unmarshal(bs, &config)
	if err != nil {
		log.Fatal("配置文件读取反序列化出错:", err)
	}
	return nil
}
